function func(color: `#${string}`) {
  return color;
}

// Argument of type '"aaa"' is not assignable to parameter of type '`#${string}`'.
// func('aaa');

func('#aaa');

type IsTwo<T> = T extends 2 ? true : false;
type Result1 = IsTwo<1>;
type Result2 = IsTwo<2>;

const result1: Result1 = false;
const result2: Result2 = true;

type Head<Arr extends unknown[]> = Arr extends [infer Value, ...unknown[]] ? Value : never;
type Result3 = Head<[1, 2, 3]>;
type Result4 = Head<[]>;

type ObjectType = { a: number } & { c: boolean };

type MapType1<T> = {
  [K in keyof T]: [T[K], T[K], T[K]];
};

type Result5 = MapType1<{ a: 1; b: 2 }>;

type MapType2<T> = {
  [K in keyof T as `${K & string}${K & string}${K & string}`]: [T[K], T[K], T[K]];
};

type Result6 = MapType2<{ a: 1; b: 2 }>;

type P = Promise<'limit'>;
type ValueType<P> = P extends Promise<infer Value> ? Value : never;
type Result7 = ValueType<P>;

type Tail<Arr extends unknown[]> = Arr extends [...unknown[], infer Rest] ? Rest : never;
type Result8 = Tail<[1, 2, 3]>;

type PopArr<Arr extends unknown[]> = Arr extends []
  ? []
  : Arr extends [...infer X, unknown]
  ? X
  : never;

type Result9 = PopArr<[1, 2, 3]>;
type Result10 = PopArr<[]>;

type ShiftArr<Arr extends unknown[]> = Arr extends []
  ? []
  : Arr extends [unknown, ...infer Rest]
  ? Rest
  : never;

type Result11 = ShiftArr<[1, 2, 3]>;

type StartsWith<T extends string, U extends string> = T extends `${U}${string}` ? true : false;
type Result12 = StartsWith<'limit test', 'limit'>;

type TrimRight<Str extends string> = Str extends `${infer Rest}${' ' | '\n' | '\t'}`
  ? TrimRight<Rest>
  : Str;

type Result14 = TrimRight<'limit\n \t'>;

type TrimLeft<Str extends string> = Str extends `${' ' | '\n' | '\t'}${infer Rest}`
  ? TrimLeft<Rest>
  : Str;

type Result15 = TrimLeft<'  limit'>;

type Trim<Str extends string> = TrimRight<TrimLeft<Str>>;
type Result16 = Trim<'  limit  '>;

type GetParameters<Func> = Func extends (...args: infer Args) => unknown ? Args : never;

function fn(name: string, age: number): string {
  return name + age;
}

type Result17 = GetParameters<typeof fn>;

type GetReturnType<Func> = Func extends (...args: infer _) => infer ReturnType ? ReturnType : never;
type Result18 = GetReturnType<typeof fn>;
type Result19 = GetReturnType<() => 'limit'>;

class Test {
  public name: string;
  protected age: number;
  private others: string[];

  constructor() {
    this.name = 'limit';
    this.age = 10;
    this.others = ['1'];
  }

  say(this: Test) {
    console.log(this.others);
    return this.name;
  }
}

type GetThisParameterType<T> = T extends (this: infer ThisType, ...args: infer _) => unknown
  ? ThisType
  : unknown;

const test = new Test();
test.say();
/*  Argument of type '{}' is not assignable to parameter of type 'Test'.
    Type '{}' is missing the following properties from type 'Test': name, say
test.say.call({});
*/
test.say.call(test);
type Result20 = GetThisParameterType<typeof test.say>;

interface Person {
  name: string;
}

interface PersonConstructor {
  new (name: string): Person;
}

type GetInstanceType<ConstructorType> = ConstructorType extends new (
  ...args: infer _
) => infer InstanceType
  ? InstanceType
  : unknown;

type Result21 = GetInstanceType<PersonConstructor>;

type GetConstructorParameters<ConstructorType> = ConstructorType extends new (
  ...args: infer ParametersType
) => unknown
  ? ParametersType
  : never;

type Result22 = GetConstructorParameters<PersonConstructor>;

type GetRefProps<Props> = 'ref' extends keyof Props
  ? Props extends { ref?: infer Value | undefined }
    ? Value
    : never
  : never;

type Result23 = GetRefProps<{ ref?: 123; name: 'limit' }>;
